
package com.zhongwang.mms.module.buy.listner;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.zhongwang.mms.common.ImportCallBack;
import com.zhongwang.mms.gen.entity.BReportPlan;
import com.zhongwang.mms.gen.entity.TWarehouseInfo;
import com.zhongwang.mms.module.basic.service.BoardService;
import com.zhongwang.mms.module.buy.dao.BuyPlanDao;
import com.zhongwang.mms.module.buy.model.MergeModel;
import com.zhongwang.mms.module.buy.model.ShoppingPlanImportErrorModel;
import com.zhongwang.mms.module.buy.model.ShoppingPlanModel;
import com.zhongwang.mms.util.BigDecimalUtils;
import com.zhongwang.mms.util.CodeUtil;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.ArrayStack;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Description: 采购计划导入 listener
 * @Author: China.wsg
 * @Date: 2020/01/09 16:38
 */
public class ShoppingPlanListener extends AnalysisEventListener<ShoppingPlanModel> {

    private BuyPlanDao buyPlanDao;
    private ImportCallBack callBack;
    private List<ShoppingPlanModel> models = new ArrayList<>();
    private List<TWarehouseInfo> warehouses;
    /**╭────────────────────────────────────────────────────────────────────╮
    *  │  @属性名: exceptionList                                             │
    *  │  @属性说明: 异常信息行号列表                                          │
    *  │  @作者: 徐一贺                                                      │
    *  │  @编程时间: 2020/8/1 15:26                                          │
    *  │  @版本号：v1.0                                                      │
    *  ╰────────────────────────────────────────────────────────────────────╯*/
    private List<Integer> exceptionList = new ArrayList<>();
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @属性名: index                                                     │
     *  │  @属性说明: 行号                                                     │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:26                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    private Integer index;
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @属性名: sppMergeIdSet                                             │
     *  │  @属性说明: 记录合报ID                                               │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:26                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    private Set<String> sppMergeIdSet = new HashSet<String>();
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @属性名: errorModelList                                            │
     *  │  @属性说明: 错误模型记录                                              │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:26                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    private Set<ShoppingPlanImportErrorModel> errorModelList = new HashSet<>();
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @属性名: mergeModelList                                            │
     *  │  @属性说明: 可能合报组集合                                            │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:26                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    private List<MergeModel> mergeModelList = new ArrayList<MergeModel>();
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @属性名: tureMergeModelList                                        │
     *  │  @属性说明: 真合报组集合                                             │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:26                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    private List<MergeModel> tureMergeModelList = new ArrayList<MergeModel>();
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @方法名: ShoppingPlanListener                                      │
     *  │  @方法说明: 构造函数                                                 │
     *  │  @参数说明: [context]                                               │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:24                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    public ShoppingPlanListener(BuyPlanDao buyPlanDao,
                                ImportCallBack callBack,
                                List<TWarehouseInfo> warehouses) {
        this.buyPlanDao = buyPlanDao;
        this.callBack = callBack;
        this.warehouses = warehouses;
        this.index = 0;
    }


    @Override
     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @方法名: invoke                                                    │
     *  │  @方法说明: 获取数据                                                 │
     *  │  @参数说明: [context]                                               │
     *  │  @返回类型说明: void                                                │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:24                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    public void invoke(ShoppingPlanModel data, AnalysisContext context) {
        ShoppingPlanImportErrorModel errorModel;
        BReportPlan reportPlan;
        StringBuffer errorInfo = new StringBuffer("");
        if (data.getRppId() == null) {
            errorInfo.append("提报计划ID不可为空！\n");
        } else if (buyPlanDao.getReportPlanById(data.getRppId()) == null) {
            errorInfo.append("此提报计划因修改或被删除！\n");
        }

        if (data.getSppMatDesc() == null) {
            errorInfo.append("采购计划物料描述不可为空！\n");
        }

        if (data.getSppNum() == null) {
            errorInfo.append("采购数量不可为空！\n");
        } else if (data.getSppNum() < 0) {
            errorInfo.append("采购数量必须大于0！\n");
        }

        if (data.getSppSapCode() == null) {
            errorInfo.append("sap物料编码不可为空！\n");
        }

        if (data.getSppProjectName() == null) {
            errorInfo.append("备注计划用途不可为空！\n");
        }

        if (data.getSppPayCycle() == null) {
            errorInfo.append("交货周期不可为空！\n");
        }

        if (data.getWhiName() == null) {
            errorInfo.append("仓库名称不可为空！\n");
        }

        if (data.getSppBuyer() == null) {
            errorInfo.append("业务员不可为空！\n");
        }

        if (data.getSppMergeFlag() == null && data.getSppMergeId() != null && !data.getSppMergeId().equals("")) {
            errorInfo.append("合报ID已填写，但合报标识未填写！\n");
        }
        if (data.getSppMergeId() == null && data.getSppMergeFlag() != null && !data.getSppMergeFlag().equals("")) {
           if("合报".equals(data.getSppMergeFlag())){
               errorInfo.append("合报标识已填写正确，但合报ID未填写！\n");
           }else {
               errorInfo.append("合报标识填写错误，合报ID未填写！\n");
           }
        }
        if(data.getSppMergeFlag()!=null){
            data.setSppMergeFlag(data.getSppMergeFlag().trim().replace("\n","").replace("\r","").replace("\t",""));
        }
        if(data.getSppMergeId()!=null) {
            data.setSppMergeId(data.getSppMergeId().trim().replace("\n", "").replace("\r", "").replace("\t", ""));
        }
        data.setSppErrorInfo(errorInfo.toString());
        reportPlan = buyPlanDao.getReportPlanById(data.getRppId());
        if(reportPlan!=null){
            data.setSppStandardNo(reportPlan.getRppStandardNo());
            data.setSppProjectCode(CodeUtil.projectCodeHandle(reportPlan.getRppProjectCode()));
            data.setSppPart(reportPlan.getRppPart());
            data.setSppDesigner(reportPlan.getRppDesigner());
            data.setSppCreateTime(reportPlan.getRppCreateTime());
            data.setSppCreateUser(reportPlan.getRppCreateUser());
            data.setSppTypeName(reportPlan.getRppTypes());
            data.setSppTypeId(reportPlan.getRppTypeId());
            data.setSppPlanner(reportPlan.getRppPlanner());
        }

        if (data.getWhiName() != null) {
            data.setSppWhiId(getWareHouse(data.getWhiName()).getWhiId());
        }
        data.setSppStatus(1);
        data.setSppImportStatus(1);
        data.setSppChangeStatus(0);
        data.setSppIntegraFlag(0);
        data.setSppPreStatus(0);
        data.setRowIndex(index);
        models.add(data);
        sppMergeIdSet.add(data.getSppMergeId());
        index++;


//        buyPlanDao.insert(data);
//        buyPlanDao.updateReportPlanById(reportPlan.getRppId(), data.getSppId());

    }

     /**╭────────────────────────────────────────────────────────────────────╮
     *  │  @方法名: getWareHouse                                              │
     *  │  @方法说明: 根据仓库名称获取仓库实体                                   │
     *  │  @参数说明: [context]                                               │
     *  │  @返回类型说明: TWarehouseInfo 仓库                                  │
     *  │  @作者: 徐一贺                                                      │
     *  │  @编程时间: 2020/8/1 15:24                                          │
     *  │  @版本号：v1.0                                                      │
     *  ╰────────────────────────────────────────────────────────────────────╯*/
    private TWarehouseInfo getWareHouse(String name) {
        for (TWarehouseInfo warehouse : warehouses) {
            if (warehouse.getWhiName() != null && warehouse.getWhiName().equals(name)) {
                return warehouse;
            }
        }
        return null;
    }

    @Override
    /**╭────────────────────────────────────────────────────────────────────╮
    *  │  @方法名: doAfterAllAnalysed                                        │
    *  │  @方法说明: 执行获取数据后的操作                                      │
    *  │  @参数说明: [context]                                               │
    *  │  @返回类型说明: void                                                │
    *  │  @作者: 徐一贺                                                      │
    *  │  @编程时间: 2020/8/1 15:24                                          │
    *  │  @版本号：v1.0                                                      │
    *  ╰────────────────────────────────────────────────────────────────────╯*/
    public void doAfterAllAnalysed(AnalysisContext context) {
       try{
           //真分组index集合
           List<Integer> tureMergeIndex = new ArrayList<>();
           for (Integer rowIndex : exceptionList) {
               for (ShoppingPlanModel model : models) {
                   if (model.getRowIndex().equals(rowIndex)) {
                       model.setSppErrorInfo(model.getSppErrorInfo() + "此行数据个数不正确！\n");
                       break;
                   }
               }
           }
           //合报分组
           for (ShoppingPlanModel model : models) {
               if(model.getSppErrorInfo().length()==0){
                   if (mergeModelList.size() == 0 && model.getSppErrorInfo().length() == 0) {
                       if(model.getSppMergeFlag()!=null && !model.getSppMergeFlag().trim().equals("") && !model.getSppMergeFlag().equals("合报")){
                           if(!model.getSppErrorInfo().contains("合报标识只能填写“合报”这两个字，或者不填。\n")){
                               model.setSppErrorInfo(model.getSppErrorInfo()+"合报标识只能填写“合报”这两个字，或者不填。\n");
                               addErrorModel(model);
                           }
                       }else if((model.getSppMergeFlag()==null || model.getSppMergeFlag().trim().equals("")) && model.getSppMergeId()!=null && !model.getSppMergeId().trim().equals("")){
                           if(!model.getSppErrorInfo().contains("合报ID已填写，但合报标识未填写。\n")){
                               model.setSppErrorInfo(model.getSppErrorInfo()+"合报ID已填写，但合报标识未填写。\n");
                               addErrorModel(model);
                           }
                       }else if(model.getSppMergeFlag()!=null && !model.getSppMergeFlag().trim().equals("") && (model.getSppMergeId()==null || model.getSppMergeId().trim().equals(""))){
                           if(!model.getSppErrorInfo().contains("合报标识已填写，但合报ID未填写。\n")){
                               model.setSppErrorInfo(model.getSppErrorInfo()+"合报标识已填写，但合报ID未填写。\n");
                               addErrorModel(model);
                           }
                       }
                       else if(model.getSppMergeFlag()!=null && !model.getSppMergeFlag().trim().equals("") && model.getSppMergeId()!=null && !model.getSppMergeId().trim().equals("")){
                           MergeModel mergeModelInit = new MergeModel();
                           mergeModelInit.setTopModel(model);
                           mergeModelInit.setMergeNum(1);
                           mergeModelInit.setMergeId(model.getSppMergeId());
                           List<ShoppingPlanModel> mergePlanList = new ArrayList<>();
                           mergePlanList.add(model);
                           mergeModelInit.setMergePlanList(mergePlanList);
                           mergeModelList.add(mergeModelInit);
                       }
                   }
                   boolean isNotExists = true;
                   for (MergeModel mergeModels : mergeModelList) {
                       if(model.getSppMergeFlag()!=null && !model.getSppMergeFlag().trim().equals("") && !model.getSppMergeFlag().equals("合报")){
                           if(!model.getSppErrorInfo().contains("合报标识只能填写“合报”这两个字，或者不填。\n")) {
                               model.setSppErrorInfo(model.getSppErrorInfo() + "合报标识只能填写“合报”这两个字，或者不填。\n");
                               addErrorModel(model);
                           }
                       }else if (model.getSppMergeId()!=null && mergeModels.getMergeId().equals(model.getSppMergeId()) && !mergeModels.getMergePlanList().contains(model)) {
                           isNotExists = false;
                           List<ShoppingPlanModel> mergePlanList = mergeModels.getMergePlanList();
                           mergePlanList.add(model);
                           mergeModels.setMergePlanList(mergePlanList);
                           mergeModels.setMergeNum(mergeModels.getMergeNum() + 1);

                           break;
                       }
                   }
                   if(model.getSppMergeFlag()!=null && !model.getSppMergeFlag().trim().equals("") && !model.getSppMergeFlag().equals("合报")){
                       if(!model.getSppErrorInfo().contains("合报标识只能填写“合报”这两个字，或者不填。\n")) {
                           model.setSppErrorInfo(model.getSppErrorInfo() + "合报标识只能填写“合报”这两个字，或者不填。\n");
                           addErrorModel(model);
                       }
                   }else if (model.getSppMergeId()!=null && isNotExists) {
                       MergeModel mergeModel = new MergeModel();
                       mergeModel.setTopModel(model);
                       mergeModel.setMergeNum(1);
                       mergeModel.setMergeId(model.getSppMergeId());
                       List<ShoppingPlanModel> mergePlanList = new ArrayList<>();
                       mergePlanList.add(model);
                       mergeModel.setMergePlanList(mergePlanList);
                       boolean isNotExistsByMergeModel = true;
                       for (MergeModel mergeModels : mergeModelList) {
                           if(mergeModels.getTopModel().equals(model)){
                               isNotExistsByMergeModel=false;
                               break;
                           }
                       }
                       if(isNotExistsByMergeModel){
                           mergeModelList.add(mergeModel);
                       }
                   }
               }
           }
           //处理分组，成员为1的不可合报
           for (MergeModel mergeModel : mergeModelList) {
               if (mergeModel.getMergeNum().equals(1)) {
                   for (ShoppingPlanModel model : models) {
                       if (mergeModel.getTopModel().getRowIndex().equals(model.getRowIndex())) {
                           if(!model.getSppErrorInfo().contains("此条采购计划只有一条提报计划，无法合报！\n")) {
                               model.setSppErrorInfo(model.getSppErrorInfo() + "此条采购计划只有一条提报计划，无法合报！\n");
                           }
                           break;
                       }
                   }
               }
               //处理分组，获取真合报组
               else {
                   mergeModel.setIfMerge(true);
                   //检测如果合报计划中包含sap物料编码不同的计划，列为错误数据，此批次的合报不进行合报。
                   for (ShoppingPlanModel shoppingPlanModel : mergeModel.getMergePlanList()) {
                       if(!shoppingPlanModel.getSppSapCode().equals(mergeModel.getTopModel().getSppSapCode())) {
                           if (!shoppingPlanModel.getSppErrorInfo().contains("与此组合报的第一条和报数据SAP物料编码不同！\n")) {
                               shoppingPlanModel.setSppErrorInfo(shoppingPlanModel.getSppErrorInfo() + "与此组合报的第一条合报数据SAP物料编码不同！\n");
                               mergeModel.setIfMerge(false);
                               addErrorModel(shoppingPlanModel);
                           }
                       }
                   }
                    if(mergeModel.getIfMerge()==false){
                        for (ShoppingPlanModel shoppingPlanModel : mergeModel.getMergePlanList()) {
                            if(shoppingPlanModel.getSppErrorInfo().length()==0){
                                shoppingPlanModel.setSppErrorInfo(shoppingPlanModel.getSppErrorInfo() + "此组成员有错误，所以此组不可合报！\n");
                                mergeModel.setIfMerge(false);
                                addErrorModel(shoppingPlanModel);
                            }
                        }
                    }
                   if(mergeModel.getIfMerge()){
                       tureMergeModelList.add(mergeModel);
                   }
               }
           }
           //有合报
           if (tureMergeModelList.size() > 0) {
               //1.开始处理合报
               for (MergeModel merge :tureMergeModelList) {
                   //如果库合报
                   if(merge.getIfMerge()){
                       Double buyNum = 0d;
                       for (ShoppingPlanModel shoppingPlanModel :merge.getMergePlanList()) {
                           buyNum = BigDecimalUtils.add(buyNum,shoppingPlanModel.getSppNum());
                       }
                       ShoppingPlanModel insertShoppingPlanModel = merge.getTopModel();
                       insertShoppingPlanModel.setSppNum(buyNum);
                       buyPlanDao.insert(insertShoppingPlanModel);
                       for (ShoppingPlanModel shoppingPlanModel :merge.getMergePlanList()) {
                           buyPlanDao.updateReportPlanById(shoppingPlanModel.getRppId(), insertShoppingPlanModel.getSppId());
                           tureMergeIndex.add(shoppingPlanModel.getRowIndex());
                       }
                   }
               }
               //2.处理未合报的采购计划
               for (ShoppingPlanModel model : models) {
                   if(!tureMergeIndex.contains(model.getRowIndex()) && model.getSppErrorInfo().length()==0){
                       buyPlanDao.insert(model);
                       buyPlanDao.updateReportPlanById(model.getRppId(), model.getSppId());
                   }else if(model.getSppErrorInfo().length()>0){
                       addErrorModel(model);
                   }
               }
           }
           //无合报
           else {
               for (ShoppingPlanModel model : models) {
                   if (model.getSppErrorInfo().length() > 0) {
                       addErrorModel(model);
                   }else {
                       buyPlanDao.insert(model);
                       buyPlanDao.updateReportPlanById(model.getRppId(), model.getSppId());
                   }
               }
           }

           //处理异常数据
           if (errorModelList.size() > 0) {
               callBack.onWarning(new ArrayList<>(errorModelList));
           } else {
               callBack.onSuccess();
           }
       }catch (Exception ex){
           callBack.onWarning(new ArrayList<>(errorModelList));
       }
    }
    /**╭────────────────────────────────────────────────────────────────────╮
    *  │  @方法名: addErrorModel                                             │
    *  │  @方法说明: 添加错误信息 含有错误信息的模型                            │
    *  │  @参数说明: [model]                                                 │
    *  │  @返回类型说明: void                                                │
    *  │  @作者: 徐一贺                                                      │
    *  │  @编程时间: 2020/8/1 15:50                                          │
    *  │  @版本号：v1.0                                                      │
    *  ╰────────────────────────────────────────────────────────────────────╯*/
    private void addErrorModel(ShoppingPlanModel model) {
        ShoppingPlanImportErrorModel model1 = new ShoppingPlanImportErrorModel(model.getRppId(),
                model.getRppProjectCode(),
                model.getRppProjectName(),
                model.getRppDesigner(),
                model.getRppMatDesc(),
                model.getRppNum(),
                model.getRppUnit(),
                model.getRppStandardNo(),
                model.getRppBrand(),
                model.getRppRemark(),
                model.getRppCreateTime(),
                model.getSppSapCode(),
                model.getSppMatDesc(),
                model.getSppNum(),
                model.getSppBrand(),
                model.getSppPayCycle(),
                model.getWhiName(),
                model.getSppBuyer(),
                model.getSppProjectName(),
                model.getSppRemark(),
                model.getSppMergeFlag(),
                model.getSppMergeId(),
                model.getSppErrorInfo());
        errorModelList.add(model1);
    }

    @Override
    /**╭──────────────────────────────────────────────────────────────────────╮
    *  │  @方法名: onException                                                 │
    *  │  @方法说明: 异常捕获                                                   │
    *  │  @参数说明: [exception, context]异常对象和异常内容                      │
    *  │  @返回类型说明: void                                                  │
    *  │  @作者: 徐一贺                                                        │
    *  │  @编程时间: 2020/8/1 15:19                                            │
    *  │  @版本号：v1.0                                                        │
    *  ╰──────────────────────────────────────────────────────────────────────╯*/
    public void onException(Exception exception, AnalysisContext context) {
        exceptionList.add(index);
        index++;
        //处理异常数据
        if (errorModelList.size() > 0) {
            callBack.onWarning(new ArrayList<>(errorModelList));
        } else {
            callBack.onSuccess();
        }
    }
}